﻿//////////////////////////////////////////////////////////////////
//
// MRUFile.cs
//
// Copyright (c) 2012 Dan Pike. All rights reserved
//
// Refer to license.txt for any license restrictions.
// 
using Logger4Net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace Utilities
{
   public class MRUFile
   {
      public class ClickedEventArgs : EventArgs
      {
         public int index;
         public string filename;
      }
      public delegate void ClickedEventHandler(object sender, ClickedEventArgs eventArgs);
      public event ClickedEventHandler eventClicked;

      //////////////////////////////////////////////////////////////////////////
      //
      public MRUFile()
      {
         filenames_ = new List<string>();
         menuSeparator_ = new ToolStripSeparator();
         menuSeparator_.Visible = false;
         menus_ = new List<ToolStripMenuItem>();
         capacity = 4;
      }

      //////////////////////////////////////////////////////////////////////////
      //
      public ToolStripMenuItem fileMenu
      {
         get { return menu_; }
         set
         {
            if (null != menu_)
            {
               // Drop them from the old menu
               menus_.ToList().ForEach(menuItem => menu_.DropDownItems.Remove(menuItem));
               menu_.DropDownItems.Remove(menuSeparator_);
            }

            menu_ = value;

            // Add them to the new menu
            menu_.DropDownItems.Add(menuSeparator_);
            menus_.ToList().ForEach(menuItem => menu_.DropDownItems.Add(menuItem));
         }
      }

      //////////////////////////////////////////////////////////////////////////
      //
      public MRUArchive config
      {
         get { return config_; }
         set
         {
            config_= value;
            loadConfig();
         }
      }

      //////////////////////////////////////////////////////////////////////////
      //
      public void addFile(string filename)
      {
         try
         {
            filenames_.RemoveAll(storedName => Path.GetFullPath(filename) == Path.GetFullPath(storedName));
            filenames_.Insert(0, filename);
            if (capacity_ < filenames_.Count)
            {
               filenames_.RemoveRange(capacity_, filenames_.Count - capacity_);
            }
            menuSeparator_.Visible = (0 < capacity_);
            
            // Rebuild the menus
            for (int index = 0; index < menus_.Count; ++index)
            {
               updateMenuItem(index);
            }
            saveConfig();
         }
         catch (System.Exception ex)
         {
            logger_.exception(ex);
         }
      }

      //////////////////////////////////////////////////////////////////////////
      //
      public int capacity
      {
         get { return capacity_; }
         set
         {
            capacity_ = value;

            // Drop the excess
            if (capacity_ < filenames_.Count)
            {
               filenames_.RemoveRange(capacity_, filenames_.Count - capacity_);
            }
            if (capacity_ < menus_.Count)
            {
               if (null != menu_)
               {
                  menus_.Skip(capacity_).ToList().ForEach(menuItem => menu_.DropDownItems.Remove(menuItem));
               }
               if (0 == capacity_)
               {
                  menu_.DropDownItems.Remove(menuSeparator_);
               }
               menus_.RemoveRange(capacity_, menus_.Count - capacity_);
            }
            else
            {
               while (capacity_ > menus_.Count)
               {
                  // Add more menu items to match the new capacity
                  ToolStripMenuItem mruMenu = new ToolStripMenuItem();
                  mruMenu.Click += new EventHandler(mruMenu_Click);
                  menus_.Add(mruMenu);
                  updateMenuItem(menus_.Count - 1);
                  if (null != menu_)
                  {
                     menu_.DropDownItems.Add(mruMenu);
                  }
               }
            }
            menuSeparator_.Visible = (0 < capacity_) && (0 < filenames_.Count);
         }
      }

      //////////////////////////////////////////////////////////////////////////
      //
      private void updateMenuItem(int index)
      {
         try
         {
            ToolStripMenuItem mruMenu = menus_[index];
            string thisFilename = (index < filenames_.Count) ? filenames_[index] : null;
            mruMenu.Text = string.Format("&{0}. {1}", index + 1,
               Global.normalizePath(thisFilename ?? string.Empty, true));
            mruMenu.Tag = thisFilename;
            mruMenu.Visible = !string.IsNullOrWhiteSpace(thisFilename);
         }
         catch (System.Exception ex)
         {
            logger_.exception(ex);
         }
      }

      //////////////////////////////////////////////////////////////////////////
      //
      private void mruMenu_Click(object sender, EventArgs e)
      {
         try
         {
            if (null != eventClicked)
            {
               ToolStripMenuItem menuItem = sender as ToolStripMenuItem;
               if (null != menuItem)
               {
                  ClickedEventArgs eventArgs = new ClickedEventArgs();
                  eventArgs.index = menus_.IndexOf(menuItem);
                  eventArgs.filename = menuItem.Tag as string;
                  eventClicked(this, eventArgs);
               }
            }
         }
         catch (System.Exception ex)
         {
            logger_.exception(ex);
         }
      }

      //////////////////////////////////////////////////////////////////////////
      //
      public List<string> allFilenames
      {
         get { return new List<string>(filenames_); }
         set
         {
            if (capacity > value.Count)
            {
               // Drop the excess
               int saveCapacity = capacity;
               capacity = value.Count;
               capacity = saveCapacity;
            }

            filenames_ = new List<string>(value);
            for (int index = 0; index < capacity; ++index)
            {
               updateMenuItem(index);
            }
         }
      }

      //////////////////////////////////////////////////////////////////////////
      //
      private void loadConfig()
      {
         try
         {
            if (null == config_)
            {
               return;
            }
            config_.OfType<MRUArchiveFilename>().Reverse<MRUArchiveFilename>().ToList()
               .ForEach(filename => addFile(filename.path));
         }
         catch (System.Exception ex)
         {
            logger_.exception(ex);
         }
      }

      //////////////////////////////////////////////////////////////////////////
      //
      private void saveConfig()
      {
         try
         {
            if (null == config_)
            {
               return;
            }
            config_.Clear();
            filenames_.ForEach(filename =>
               {
                  MRUArchiveFilename element = new MRUArchiveFilename();
                  element.path = filename;
                  config_.Add(element);
               });
         }
         catch (System.Exception ex)
         {
            logger_.exception(ex);
         }
      }

      //////////////////////////////////////////////////////////////////////////
      //
      public string firstFilename
      {
         get { return (0 < filenames_.Count) ? filenames_[0] : string.Empty;  }
      }

      //////////////////////////////////////////////////////////////////////////
      //
      private Logger logger_ = new Logger(typeof(MRUFile));
      private MRUArchive config_;
      private ToolStripSeparator menuSeparator_;
      private ToolStripMenuItem menu_;
      private List<ToolStripMenuItem> menus_;
      private List<string> filenames_;
      private int capacity_;
   }
}
